package com.yuyu.shop.domain.order.DO;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.yuyu.commons.exception.BusinessException;
import com.yuyu.commons.exception.TokenException;
import com.yuyu.commons.factory.RepositoryFactory;
import com.yuyu.commons.interfaces.IDomainDelete;
import com.yuyu.commons.interfaces.IDomainMetaData;
import com.yuyu.commons.interfaces.IDomainSaveOrUpdate;
import com.yuyu.commons.redis.constant.KeyConstants;
import com.yuyu.commons.security.LoginContext;
import com.yuyu.commons.security.LoginUser;
import com.yuyu.shop.api.apimodel.order.dto.OrderCreateDTO;
import com.yuyu.shop.application.service.tcc.OrderAssembleTccService;
import com.yuyu.shop.domain.build.NormalOrderBuilder;
import com.yuyu.shop.domain.build.chain.inspector.manager.OrderInspectorManager;
import com.yuyu.shop.domain.build.construct.NormalOrderConstruct;
import com.yuyu.shop.domain.order.repository.OrderRepository;
import com.yuyu.shop.domain.order.repository.SecKillRepository;
import com.yuyu.shop.infrastructure.general.cache.OrderCache;
import com.yuyu.shop.infrastructure.persistence.convert.OrderPoConvert;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Objects;

/**
 * @author 订单信息
 * @version 1.0
 * @description: TODO
 * @date 2022/8/3 9:17
 */
@Data
@Accessors(chain = true)
@Slf4j
public class OrderDO implements IDomainMetaData, IDomainDelete, IDomainSaveOrUpdate, Serializable {

    private static final OrderRepository orderRepository = RepositoryFactory.get(OrderRepository.class);

    private static final OrderCache  orderCache = RepositoryFactory.get(OrderCache.class);

    private static final OrderInspectorManager  manager = RepositoryFactory.get(OrderInspectorManager.class);

    private static final SecKillRepository secKillOrderRepository = RepositoryFactory.get(SecKillRepository.class);

    private static final OrderAssembleTccService orderAssembleTccService = RepositoryFactory.get(OrderAssembleTccService.class);

    private static final NormalOrderBuilder normalOrderBuilder = RepositoryFactory.get(NormalOrderBuilder.class);


    private Long shopId; //shopId

    private Long goodId; //skuId

    private String id;  //主键Id

    private String orderId; //订单唯一ID

    private String shopName; //商店名

    private String shopAddress; //商家地址

    private String shopPhone; //商家电话

    private String goodsName; //商品名

    private BigDecimal originPrice; //商品原价

    private BigDecimal realPrice; //商品实价

    private Integer goodsNum; //购买数量

    private String attribute; //具体参数 如256g内存 8g运行内存 双卡双待等

    private String specification; //具体什么规格 如 iPhone13 远峰蓝

    private Integer discountType; //优惠名称 1.优惠券 2.会员 3.混合优惠

    private BigDecimal reduceAccount; //优惠了多少

    private String discountDescribe; //优惠描述信息

    private String accountName; //用户名

    private String realName; //真实名字

    private String phone; //电话号码

    private Integer status; //订单状态

    private Integer orderType; //1.普通订单 2.团购订单 3.限购订单 4.秒杀订单

    private String receiveInfo; //收获信息

    private Long userId; //用户id



    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;   //创建时间

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime updateTime; //修改时间


    @Override
    public Boolean delete(String orderId) {
        return orderRepository.delete(orderId);
    }


    @Override
    public Boolean saveOrUpdate() {
        //先判断是新增还是修改 都需要验证订单的合法性
        return isSave("normal");
    }

    /**
     * 用orderId获取order
     * @return OrderDO
     */
    public static OrderDO getByOrderId(String orderId){
        if (Objects.isNull(orderId)){
            throw new BusinessException("orderId不能为空!");
        }
               return orderRepository.getByOrderId(orderId);
            }





    public OrderCreateDO createOrder(BusinessActionContext businessActionContext,OrderCreateDTO dto){
        String orderId = normalOrderBuilder.buildOrderId(dto);
        //构建订单
       return orderAssembleTccService.tryCreate(businessActionContext ,
               dto.getOrderType(),dto.getShopId(),dto.getGoodsId(),dto.getGoodsNum(),orderId);
    }

    /**
     * 查询秒杀订单
     * @return
     */
    public OrderDO querySecKillOrder(Long goodId){
        LoginUser user = LoginContext.getUser();
        if (Objects.isNull(user) || Objects.isNull(user.getUserId())){
            throw new TokenException("用户并未登录或用户信息不完整!");
        }
       return secKillOrderRepository.getByUserId(user.getUserId(),goodId);
    }

    /**
     * 保存秒杀订单
     */
    public Boolean secKillSaveOrUpdate() {
        //先判断是新增还是修改 都需要验证订单的合法性
        return isSave("secKill");
    }

    private Boolean isSave(String type) {
        Boolean preCreateOrder = manager.inspectPreCreateOrder(this);
        if (preCreateOrder!=null){
            throw new BusinessException("订单数据验证失败!");
        }
        Boolean insertOrUpdate = Boolean.FALSE;
        if (type.equals("normal")){
                insertOrUpdate = Objects.isNull(this.getId()) ?
                orderRepository.insert(setUpdateTime(LocalDateTime.now())) :
                orderRepository.updateById(this);
        }else if (type.equals("secKill")){
            insertOrUpdate = Objects.isNull(this.getId()) ?
            secKillOrderRepository.insert(setUpdateTime(LocalDateTime.now())) :
            secKillOrderRepository.updateById(this) ;
        }
        if (insertOrUpdate){
            Boolean aBoolean = orderCache.setOneOrderInfo(OrderPoConvert.DO2PO(this));
            if (!aBoolean){
                log.error("存储订单信息失败!");
            }
        }
        return insertOrUpdate;
    }

}



